package no.uials.distsys;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Anders
 */
public class Order implements java.io.Serializable {
    private int orderID;
    private User user;
    private Map<String, OrderLine> orderLines;
    private Calendar orderDate;

    /**
     * Makes a new Order, with no OrderLines.
     * 
     * @param orderID the Order's ID.
     * @param user the User that placed the Order.
     */
    public Order(int orderID, User user) {
        this(orderID, user, new HashMap<String, OrderLine>());
    }

    /**
     * Makes a new Order containing a map of OrderLines.
     * 
     * @param orderID the Order's ID.
     * @param user the User that placed the Order.
     * @param orderLines the OrderLines.
     */
    public Order(int orderID, User user, Map orderLines) {
        this.orderID = orderID;
        this.user = user;
        this.orderLines = orderLines;
        orderDate = Calendar.getInstance();
    }
    /**
     * Makes a new Order containing a map of OrderLines.
     * 
     * @param orderID the Order ID.
     * @param user the User that placed the Order.
     * @param orderLines an array containing the OrderLines.
     */
    public Order(int orderID, User user, OrderLine... orderLines) {
        this.orderID = orderID;
        this.user = user;
        for (OrderLine ol : orderLines) {
            this.orderLines.put(ol.getArticle().getID(), ol);
        }
        orderDate = Calendar.getInstance();
    }
    
    /**
     * Makes a new OrderLine containing the given number of the given Aricle and puts it into the Order.
     * 
     * @param article the Article to put into the Order.
     * @param number the number of units to add into the Order.
     * @return the newly inserted Article.
     */
    public Article addArticle(Article article, int number) {
        String id = article.getID();
        if (orderLines.containsKey(id)) {
            orderLines.get(id).addUnits(number);
        } else {
            orderLines.put(id, new OrderLine(article, number));
        }
        return article;
    }
    
    /**
     * Removes a given number of the given Article from the Order.
     * If the number of units decends past one, the OrderLine will simply be removed.
     * 
     * @param article the Article to order fewer of.
     * @param number the amount of Articles to remove.
     * @return the handled Article.
     */
    public Article removeArticle(Article article, int number) {
        String id = article.getID();
        if (orderLines.containsKey(id)) {
            orderLines.get(id).addUnits(-number);
            if (orderLines.get(id).getUnits() == 0) {
                orderLines.remove(id);
            }
        }
        return article;
    }
    
    /**
     * Returns the Order ID.
     * 
     * @return the Order ID.
     */
    public int getOrderID() {
        return orderID;
    }
    
    /**
     * Returns the User that placed the Order.
     * 
     * @return the User.
     */
    public User getUser() {
        return user;
    }
    
    /**
     * Returns the Map of OrderLines in the order.
     * 
     * @return the map of OrderLines.
     */
    public Map<String, OrderLine> getArticles() {
        return orderLines;
    }
    
    /**
     * Returns the total number of Articles in the Order.
     * 
     * @return the total number of Articles.
     */
    public int getUnits() {
        int units = 0;
        ArrayList<OrderLine> collection = new ArrayList<>(orderLines.values());
        for (OrderLine ol : collection) {
            units += ol.getUnits();
        }
        return units;
    }
    
    /**
     * Returns the total price of the Order.
     * 
     * @return the total price.
     */
    public Double getTotal() {
        Double total = 0d;
        ArrayList<OrderLine> collection = new ArrayList(orderLines.values());
        for (OrderLine ol : collection) {
            total += ol.getArticle().getPrice() * ol.getUnits();
        }
        return total;
    }
    
    /**
     * Returns the date the Order was placed.
     * 
     * @return the Order date.
     */
    public Calendar getOrderDate() {
        return orderDate;
    }
    
    /**
     * Returns the date the order was placed as a String.
     * 
     * @return the Order date.
     */
    public String getDateString() {
        String retVal = "";
        retVal += addZero(orderDate.get(Calendar.DATE), 2) + ".";
        retVal += addZero(orderDate.get(Calendar.MONTH), 2) + ".";
        retVal += addZero(orderDate.get(Calendar.YEAR), 4);
        return retVal;
    }
    
    /**
     * Adds zeros in front of the number until it has reached the requested number of characters.
     * 
     * @param i the number.
     * @param length the requested length.
     * @return the number in String format.
     */
    private String addZero(int i, int length) {
        String retVal = "" + i;
        while (retVal.length() < length) {
            retVal = 0 + retVal;
        }
        return retVal;
    }
}